﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace TA.Turbo
{
	/// <summary>
	/// Contains information about a single HTTP header.
	/// </summary>
	public class Header
	{
		#region STATIC
		/// <summary>
		/// Parses the specified text and returns a header constructed from its value.
		/// </summary>
		/// <param name="header"></param>
		/// <returns></returns>
		public static Header FromString(string header)
		{
			if (header == null)
				throw new ArgumentNullException("header");

			Match m = Header._rgxHeader.Match(header);
			if (!m.Success) throw new ArithmeticException("Header string invalid.");

			Header h = new Header(m.Groups["Name"].Value);
			h.CompleteValue = m.Groups["CompleteValue"].Value;
			return h;
		}
		#endregion
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		/// <param name="name"></param>
		public Header(string name)
		{
			this._name = name;
		}
		#endregion
		#region PROPS
		/// <summary>
		/// Gets the name of this header.
		/// </summary>
		public string Name { get { return this._name; } }
		/// <summary>
		/// Gets the complete value of this header.
		/// </summary>
		/// <remarks>
		/// This returns all of the text in the header which follows the name and the ':' character.
		/// </remarks>
		public string CompleteValue
		{
			get
			{
				return string.Format("{0}; {1}",
					this.Value,
					this.Additional.GetJoinedStrings(";", false, "{0}={1}", kv => kv.Key, kv => kv.Value));
			}
			set
			{
				if (value == null)
				{
					this.Value = null;
					this.Additional.Clear();
				}
				else
				{
					Match m = Header._rgxCompleteValue.Match(value);
					this.Value = m.Groups["Value"].Value;
					this.Additional.Clear();
					for (int i = 0; i < m.Groups["AName"].Captures.Count; ++i)
					{
						this.Additional[m.Groups["AName"].Captures[i].Value] = m.Groups["Value"].Captures[i + 1].Value;
					}
				}
			}
		}
		/// <summary>
		/// Gets the main value of this header.
		/// </summary>
		public string Value { get; set; }
		/// <summary>
		/// Gets the additional names and values of this header.
		/// </summary>
		public Dictionary<string, string> Additional { get { return this._additional; } }
		#endregion
		#endregion
		#region INTERNAL
		#region CONST/STATIC
		const string ValueRegex = @"((""(?<Value>[^""]*)"")|(?<Value>[^""]([^;]*)))";
		static readonly Regex _rgxCompleteValue = new Regex(@"^" + ValueRegex + @"(;\s*(?<AName>[^=]+)\=" + ValueRegex + ")*$"),
			_rgxHeader = new Regex(@"^(?<Name>[^:]+):\s*(?<CompleteValue>.*)$");
		#endregion
		#region VARS
		string _name;
		Dictionary<string, string> _additional = new Dictionary<string, string>();

		#endregion
		#endregion
	}
}
